using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;

namespace SymAutomate.Util
{
    /// <summary>
    /// Handles Util functions
    /// Error Numbers 620-699; Reference file ErrorNumbers.txt for more information.
    /// 620 Error: Error Parsing SystemDate.
    /// 630 Error: Could not read registry. %errormessage%.
    /// 631 Error: Could not write to registry. %errormessage%.
    /// 632 Error: Encryption Key not set or could not be read.
    /// </summary>
    class Driver : DriverBase, DriverInterface
    {
        private Parameters __Parameters;

        public Driver()
            : base()
        {
        }

        public Driver(ConsoleArguments _ConsoleArguments, HostTelnetConnection.Driver _HostTelnetConnectionDriver)
            : base(_HostTelnetConnectionDriver)
        {
            __Parameters = new Parameters(_ConsoleArguments, base.ConsoleHelpList);
        }

        /// <summary>
        /// Defines the command to function mapping;
        /// First parameter is what to expect as "command" from commmand line;
        /// Second parameter is the function name (case must match);
        /// </summary>
        public void PopulateCommandToFunctionMapping()
        {
            CommandToFunctionMapping.Add("SimulateAixLogon".ToLower(), "SimulateAixLogon");
            CommandToFunctionMapping.Add("SimulateSymopLogon".ToLower(), "SimulateSymopLogon");
            CommandToFunctionMapping.Add("SimulateSymLogon".ToLower(), "SimulateSymLogon");
            CommandToFunctionMapping.Add("GetSystemDate".ToLower(), "GetSystemDate");
            CommandToFunctionMapping.Add("Version".ToLower(), "Version");
            CommandToFunctionMapping.Add("GenerateEncryptionKey".ToLower(), "GenerateEncryptionKey");
            CommandToFunctionMapping.Add("SetEncryptedValue".ToLower(), "SetEncryptedValue");
        }

        /// <summary>
        /// Defines the help text for this driver
        /// </summary>
        public void PopulateConsoleHelp()
        {
            ConsoleHelp _ConsoleHelp = new ConsoleHelp("SimulateAixLogon");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("SimulateSymopLogon");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("SimulateSymLogon");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("GetSystemDate");
            _ConsoleHelp.Parameters.Add("DateFormat");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("Version");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("GenerateEncryptionKey");
            ConsoleHelpList.Add(_ConsoleHelp);

            _ConsoleHelp = new ConsoleHelp("SetEncryptedValue");
            _ConsoleHelp.Parameters.Add("EncryptKey");
            _ConsoleHelp.Parameters.Add("EncryptValue");
            ConsoleHelpList.Add(_ConsoleHelp);
        }

        /// <summary>
        /// Driver Function: 
        /// </summary>
        public void SimulateAixLogon()
        {
            try
            {
                HostTelnetConnectionDriver.AixLogin();
            }
            finally
            {
                HostTelnetConnectionDriver.TelnetCloseConnection();
            }
        }

        /// <summary>
        /// Driver Function: 
        /// </summary>
        public void SimulateSymopLogon()
        {
            try
            {
                HostTelnetConnectionDriver.SymopLogin();
            }
            finally
            {
                HostTelnetConnectionDriver.TelnetCloseConnection();
            }
        }

        /// <summary>
        /// Driver Function: 
        /// </summary>
        public void SimulateSymLogon()
        {
            try
            {
                HostTelnetConnectionDriver.Login();
            }
            finally
            {
                HostTelnetConnectionDriver.TelnetCloseConnection();
            }
        }

        /// <summary>
        /// Driver Function: Gets the system date of the specified sym
        /// </summary>
        public void GetSystemDate()
        {
            string s = "";

            try
            {
                HostTelnetConnectionDriver.Login();

                HostTelnetConnectionDriver.TelnetSend("8" + GlobalParameters.TelnetSendEndOfCommand); //Management Menu
                s = HostTelnetConnectionDriver.TelnetWaitFor("Menu Selection");
                HostTelnetConnectionDriver.LogIncommingStream(s);

                //now s has the date in mm/dd/yy format.. atempt to parse it
                System.Text.RegularExpressions.MatchCollection _MatchCollection;
                System.Text.RegularExpressions.Regex _Regex = new System.Text.RegularExpressions.Regex(@"(\d\d)/(\d\d)/(\d\d)");
                _MatchCollection = _Regex.Matches(s);
                if (_MatchCollection.Count == 1)
                {
                    DateTime _SystemDateTime = new DateTime(2000 + Convert.ToInt32(_MatchCollection[0].Groups[3].Value),
                        Convert.ToInt32(_MatchCollection[0].Groups[1].Value),
                        Convert.ToInt32(_MatchCollection[0].Groups[2].Value));
                    string _DateFormat = string.IsNullOrEmpty(__Parameters.DateFormat) ? "MMddyyyy" : __Parameters.DateFormat;
                    Console.WriteLine(_SystemDateTime.ToString(_DateFormat));
                }
                else
                {
                    throw new ReturnException("620 Error: Error Parsing SystemDate.");
                }
            }
            catch (Exception e)
            {
                if (e is Dart.Telnet.DataException)
                    s = HostTelnetConnectionDriver.LogIncommingStream(((Dart.Telnet.DataException)e).DataRead.ToString());
                else
                    s = HostTelnetConnectionDriver.LogIncommingStream(string.Empty);
                HostTelnetConnectionDriver.HandleException(e, s);
            }
            finally
            {
                HostTelnetConnectionDriver.TelnetCloseConnection();
            }
        }

        /// <summary>
        /// Driver Function: Gets the build version number
        /// </summary>
        public void Version()
        {
            Console.WriteLine("Build version is " + GetVersion());
        }

        public static string GetVersion()
        {
            return System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;
        }

        /// <summary>
        /// Driver Function: Generates the encryption key
        /// </summary>
        public void GenerateEncryptionKey()
        {
            WriteRegistryKey(@"HKEY_LOCAL_MACHINE\Software\SymAutomate", "EncryptionKey", System.Guid.NewGuid().ToString());
            Console.WriteLine("Random Encryption Key Generated!");
        }

        public static string ReadRegistryKey(string _NodePath, string _Key)
        {
            try
            {
                return Convert.ToString(Registry.GetValue(_NodePath, _Key, ""));
            }
            catch (Exception _RegistryError)
            {
                throw new ReturnException("630 Error: Could not read registry. " + _RegistryError.Message + ".");
            }
        }

        public static void WriteRegistryKey(string _NodePath, string _Key, string _Value)
        {
            try
            {
                Registry.SetValue(_NodePath, _Key, _Value);
            }
            catch (Exception _RegistryError)
            {
                throw new ReturnException("631 Error: Could not write to registry. " + _RegistryError.Message + ".");
            }
        }

        public void SetEncryptedValue()
        {
            if (string.IsNullOrEmpty(HostTelnetConnectionDriver.Parameters.EncryptionKey))
                throw new ReturnException("632 Error: Encryption Key not set or could not be read.");

            AESEncryption _AESEncryption = new AESEncryption(HostTelnetConnectionDriver.Parameters.EncryptionKey);
            string _EncryptedValue = _AESEncryption.Encrypt(__Parameters.EncryptValue);

            GlobalFunctions.WriteToConfigFile(__Parameters.EncryptKey, _EncryptedValue, 0);
        }
    }
}
